import {_decorator, Component, macro, Material, Node, Quat, randomRange, SkinnedMeshRenderer, tween, Vec3} from 'cc';
import {Skill} from "db://assets/scripts/data/model/Skill";
import {EventType} from "db://assets/scripts/common/EventType";
import {SkillConverter} from "db://assets/scripts/data/converter/SkillConverter";
import {AudioPaths} from "db://assets/scripts/common/AudioPaths";
import {LaserEffect} from "db://assets/scripts/game/effect/monsterSkill/LaserEffect";
import {WarningCircleEffect} from "db://assets/scripts/game/effect/warningSkill/WarningCircleEffect";
import {FireBallBigEffect} from "db://assets/scripts/game/effect/monsterSkill/FireBallBigEffect";
import {CharacterRigidController} from "db://assets/scripts/game/CharacterRigidController";
import {BaseInfo} from "db://assets/scripts/data/model/BaseInfo";
import {GameManager} from "db://assets/scripts/game/GameManager";
import {MonsterActionEnum} from "db://assets/scripts/game/role/monster/MonsterActionEnum";
import {UIManager} from "db://assets/scripts/common/UIManager";
import {TornadoEffect} from "db://assets/scripts/game/effect/monsterSkill/TornadoEffect";
import {EffectManager} from "db://assets/scripts/common/EffectManager";
import {AudioManager} from "db://assets/scripts/common/AudioManager";
import {ResourceUtils} from "db://assets/scripts/common/ResourceUtils";
import {WarningLineEffect} from "db://assets/scripts/game/effect/warningSkill/WarningLineEffect";
import {Stage} from "db://assets/scripts/data/model/Stage";
import {WarningStripEffect} from "db://assets/scripts/game/effect/warningSkill/WarningStripEffect";
import {DispersionEffect} from "db://assets/scripts/game/effect/monsterSkill/DispersionEffect";
import {EventManager} from "db://assets/scripts/common/EventManager";
import {MonsterModelController} from "db://assets/scripts/game/role/monster/MonsterModelController";
import {MonsterBloodBarController} from "db://assets/scripts/game/role/monster/MonsterBloodBarController";
import {FireBallEffect} from "db://assets/scripts/game/effect/monsterSkill/FireBallEffect";
import {BloodTipDirectionEnum} from "db://assets/scripts/ui/common/BloodTipDirectionEnum";
import {CSVManager} from "db://assets/scripts/common/CSVManager";
import {FightTipEnum} from "db://assets/scripts/ui/common/FightTipEnum";
import {MonsterSkillEnum} from "db://assets/scripts/game/role/monster/MonsterSkillEnum";
import {PoolManager} from "db://assets/scripts/common/PoolManager";
import {MonsterAnimationType} from "db://assets/scripts/game/role/monster/MonsterAnimationType";
import {EnergyBallEffect} from "db://assets/scripts/game/effect/monsterSkill/EnergyBallEffect";
import {Utils} from "db://assets/scripts/utils/Utils";
import {MonsterMovePatternEnum} from "db://assets/scripts/game/role/monster/MonsterMovePatternEnum";
import {DispersionSurroundEffect} from "db://assets/scripts/game/effect/monsterSkill/DispersionSurroundEffect";
import {GameState} from "db://assets/scripts/game/GameState";

const {ccclass, property} = _decorator;

/**
 * 普通怪物脚本
 */
@ccclass('MonsterController')
export class MonsterController extends Component {
    /**
     * 默认材质
     */
    @property(Material)
    public normalMaterial: Material;
    /**
     * 阵亡时候溶解材质
     */
    @property(Material)
    public dissolveMaterial: Material;
    /**
     * 怪物蒙皮组件
     */
    @property(SkinnedMeshRenderer)
    public monsterSMR: SkinnedMeshRenderer;

    /**
     * 怪物动画组件播放脚本
     */
    public monsterModelScript: MonsterModelController;
    /**
     * 怪物是否正在移动
     */
    public moving: boolean = false;
    /**
     * 怪物血条脚本
     */
    public bloodBarScript: MonsterBloodBarController;
    /**
     * 血量提示方向
     */
    public bloodTipDirection: BloodTipDirectionEnum = BloodTipDirectionEnum.LEFT_UP;
    /**
     * 怪兽技能信息
     */
    public skill: Skill;
    /**
     * 所有拥有的技能信息
     */
    public allSkillInfo: string[];
    /**
     * 怪物在base表里面对应数据
     */
    public baseInfo: BaseInfo;
    /**
     * 怪物在当前层级的配置数据
     */
    public stage: Stage;
    /**
     * 当前攻击速度
     */
    public currentAttackSpeed: number = 0;
    /**
     * 预警技能脚本
     */
    public warningScript: WarningCircleEffect | WarningLineEffect | WarningStripEffect;
    /**
     * 攻击朝向
     */
    public attackForward: Vec3 = new Vec3();
    /**
     * 技能即将攻击的位置
     */
    public attackPosition: Vec3 = new Vec3();
    /**
     * 刚体
     */
    public characterRigidScript: CharacterRigidController;

    /**
     * 是否死亡
     */
    protected isDie: boolean = false;
    /**
     * 距离上次被攻击的时长
     */
    protected currentAttackInterval: number = 0;
    /**
     * 是否被玩家击中
     */
    protected isHitByPlayer: boolean = false;
    /**
     * 是否已经初始化血条
     */
    protected isInitBloodBar: boolean = false;
    /**
     * 怪物血条距离人物位置偏差
     */
    protected bloodTipOffsetPosition: Vec3 = new Vec3(0, 50, 0);
    /**
     * 怪物的血条被攻击后才会显示，且如果3秒未被攻击则会隐藏
     */
    protected hideBloodCountDown: number = 3;
    /**
     * 受击特效位置
     */
    protected hitEffectPosition: Vec3 = new Vec3(0, 0.2, 0);
    /**
     * 是否允许攻击
     */
    protected isAllowToAttack: boolean = false;
    /**
     * 怪物和玩家间距
     */
    protected playerMonsterOffset: Vec3 = new Vec3();
    /**
     * 当前Y分量旋转角度
     */
    protected currentAngleY: number = 0;
    /**
     * 水平移动距离
     */
    protected horizontal: number = 0;
    /**
     * 垂直移动距离
     */
    protected vertical: number = 0;
    /**
     * 冰冻伤害倒计时
     */
    protected iceDamageCountDown: number = 0;
    /**
     * 灼烧伤害倒计时
     */
    protected fireDamageCountDown: number = 0;
    /**
     * 技能特效节点
     */
    protected monsterSkillNode: Node = null!;
    /**
     * 当前技能索引
     */
    protected skillIndex: number = 0;
    /**
     * 怪物和玩家之间的最小距离
     */
    protected minLength: number = 3;
    /**
     * 当前移动速度
     */
    protected currentMoveSpeed: number = 0;
    /**
     * 溶解数据，v溶解程度默认为1（0为完全溶解），time为溶解所需时间
     */
    protected dissolveData: any = {uEdge: 1, time: 1};

    //移动相关
    /**
     * 移动方式
     */
    protected moveMode: number = 0;
    /**
     * 移动模式
     */
    protected movePattern: number = 0;
    /**
     * 两次移动间隔,为0表示一直移动)
     */
    protected moveFrequency: number = 0;
    /**
     * 和玩家之间的向量差
     */
    protected offsetPosition: Vec3 = new Vec3();
    /**
     * 和玩家之间的向量差
     */
    protected offsetPosition_2: Vec3 = new Vec3();
    /**
     * 和玩家的最小间距
     */
    protected mixOffset: Vec3 = new Vec3(1, 0, 1);
    /**
     * 下一步的目标位置
     */
    protected targetWorldPosition: Vec3 = new Vec3();
    /**
     * 是否旋转
     */
    protected isPlayRotate: boolean = false;
    /**
     * 当前旋转的角度
     */
    protected currentAngle: Vec3 = new Vec3()
    /**
     * 怪物角度
     */
    protected currentAngle_2: Vec3 = new Vec3();
    /**
     * 临时变量，怪物角度
     */
    protected tempAngle: Vec3 = new Vec3();
    /**
     * 旋转方向
     */
    protected rotateDirection: Vec3 = new Vec3();
    /**
     * 朝向
     */
    protected forWard: Vec3 = new Vec3();
    /**
     * 烟雾特效
     */
    protected runSmokeEffectNode: Node = null!;
    /**
     * 怪物开始角度
     */
    protected originAngle: Vec3 = new Vec3(0, -90, 0);
    /**
     * 目标旋转角度
     */
    protected targetAngle: Vec3 = new Vec3();
    /**
     * 每40ms刷新一次
     */
    protected checkInterval: number = 0.04;
    /**
     * 当前累积时间
     */
    protected currentTime: number = 0;
    /**
     *
     */
    protected bodyNode: Node = null!;
    /**
     * 当前怪物移动位置
     */
    protected currentMoveWorldPosition: Vec3 = new Vec3();
    /**
     * 是否到达
     */
    protected isArrived: boolean = false;
    /**
     * 检查当前是否移动时间间隔
     */
    protected checkMoveInterval: number = 0;
    /**
     * 之前怪物的移动坐标
     */
    protected prevMoveWorldPosition: Vec3 = new Vec3();
    /**
     * 每次移动的单位向量
     */
    protected moveUnit: Vec3 = new Vec3();
    /**
     * 达到最小距离的1.1倍视为进入最小距离
     */
    protected minLengthRatio: number = 1.1;
    /**
     * 每次随机移动位置最多计算次数
     */
    protected randomMoveTryTimes: number = 5;
    /**
     * 怪物行为
     */
    protected action: number = 0;

    private qt_0 = new Quat();
    private v3_0 = new Vec3();

    onEnable() {
        EventManager.on(EventType.MONSTER_MOVE, this.monsterMove, this);
    }

    onDisable() {
        EventManager.off(EventType.MONSTER_MOVE, this.monsterMove, this);

        //回收血条节点
        if (this.bloodBarScript) {
            if (this.bloodBarScript.node.parent) {
                PoolManager.getInstance().putNode(this.bloodBarScript.node);
            }
            this.bloodBarScript = null;
        }

        //回收预警节点
        this.recycleWarning();

        //回收技能节点
        if (this.monsterSkillNode) {
            PoolManager.getInstance().putNode(this.monsterSkillNode);
            this.monsterSkillNode = null;
        }
    }

    start() {

    }

    update(deltaTime: number) {
        //刷新溶解材质
        if (this.isDie && this.dissolveData.uEdge > 0.1) {
            this.dissolveMaterial.setProperty("uEdge", this.dissolveData.uEdge);
            return;
        }

        if (GameManager.getInstance().gameStateProxy.getGameState() !== GameState.PLAYING
            || this.isDie
            || !this.isAllowToAttack
            || !GameManager.getInstance().gamePlayerProxy.getPlayerNode()
            || GameManager.getInstance().gamePlayerProxy.getPlayerController().getIsDie()) {
            return;
        }

        //3秒未被攻击则会隐藏血条
        if (!this.isHitByPlayer && this.bloodBarScript) {
            this.currentAttackInterval += deltaTime;

            if (this.currentAttackInterval >= this.hideBloodCountDown && this.bloodBarScript.node.active) {
                this.bloodBarScript.node.active = false;
            }
        }

        //是否进行移动
        if (this.moving) {
            if (this.movePattern === MonsterMovePatternEnum.RANDOM) {
                //如果移动到目标位置就停止移动
                let offsetLength = Utils.getTwoPositionXZLength(this.node.worldPosition.x, this.node.worldPosition.z, this.targetWorldPosition.x, this.targetWorldPosition.z);
                let offsetTarget = 0.05;

                //爆炸龙的位移是跳，不容易精准到达目标位置,把达到范围适当增大
                if (this.baseInfo.resName === 'boomDragon') {
                    offsetTarget = 0.5;
                }

                if (offsetLength <= offsetTarget && !this.isArrived) {
                    // console.log("###随机移动，到达目标位置");
                    this.isArrived = true;
                    this.stayRotateAttack();
                }

            } else if (this.movePattern === MonsterMovePatternEnum.FORWARD_PLAYER) {

                let offsetLength = Utils.getTwoPositionXZLength(this.node.worldPosition.x, this.node.worldPosition.z, this.targetWorldPosition.x, this.targetWorldPosition.z);
                // console.log("offsetLength",offsetLength);
                if (offsetLength <= 0.05 && !this.isArrived) {
                    // console.log("###面向玩家移动，到达目标位置");
                    // 进行攻击
                    this.isArrived = true;
                    this.stayRotateAttack();
                }
            }
        }

        //怪物旋转
        if (this.isPlayRotate) {
            //当前怪物角度
            this.tempAngle.set(this.node.eulerAngles);
            this.tempAngle.y = this.tempAngle.y < 0 ? this.tempAngle.y + 360 : this.tempAngle.y;

            if (this.currentAngle.length() === 0) {
                this.currentAngle.set(this.tempAngle);
            }

            this.node.eulerAngles = this.tempAngle;
            //第二个参数越小朝向越精确
            let isEqual = this.currentAngle.equals(this.targetAngle, 0.1);

            if (!isEqual) {
                Vec3.lerp(this.currentAngle, this.currentAngle, this.targetAngle, 0.167);
                this.node.eulerAngles = this.currentAngle;
            } else {
                this.isPlayRotate = false;
                this.node.eulerAngles = this.targetAngle;
                this.currentAngle.set(0, 0, 0);
            }
        }

        if (this.horizontal !== 0 || this.vertical !== 0) {
            //计算出旋转角度
            this.rotateDirection.set(this.horizontal, 0, -this.vertical);
            this.rotateDirection = this.rotateDirection.normalize();

            Quat.fromViewUp(this.qt_0, this.rotateDirection);
            Quat.toEuler(this.v3_0, this.qt_0);
            this.v3_0.y = this.v3_0.y < 0 ? this.v3_0.y + 360 : this.v3_0.y;

            this.isPlayRotate = true;

            //设置当前怪物角度为正数
            this.currentAngle_2.set(this.node.eulerAngles);
            if (this.currentAngle_2.y < 0) {
                this.currentAngle_2.y += 360;
                this.node.eulerAngles = this.currentAngle_2; // 转为0~360
            } else if (this.currentAngle_2.y > 360) {
                this.currentAngle_2.y -= 360;
                this.node.eulerAngles = this.currentAngle_2; // 转为0~360
            }

            //设置目标旋转角度
            if (!this.v3_0.equals(this.node.eulerAngles, 0.01)) {
                this.targetAngle.y = this.currentAngleY + 225;
                this.targetAngle.y = this.targetAngle.y < 0 ? this.targetAngle.y + 360 : this.targetAngle.y > 360 ? this.targetAngle.y - 360 : this.targetAngle.y;
                this.targetAngle.x = 0;
                this.targetAngle.z = 0;

                if (Math.abs(this.targetAngle.y - this.currentAngle_2.y) > 180) {
                    if (this.targetAngle.y > this.currentAngle_2.y) {
                        this.targetAngle.y -= 360;
                    } else {
                        this.targetAngle.y += 360;
                    }
                }

                //每次有新的_targetAngle之后，先将_curAngle初始化
                this.currentAngle.set(0, 0, 0);
            } else {
                this.isPlayRotate = false;
                this.node.eulerAngles = this.v3_0;
            }

            if (!this.moving) {
                return;
            }

            //怪物朝着目标位置移动：
            if (this.movePattern !== MonsterMovePatternEnum.NO_MOVE) {
                this.characterRigidScript.move(-this.moveUnit.x * this.currentMoveSpeed * GameManager.getInstance().chapter.moveSpeedAddition * 0.5 * deltaTime,
                    -this.moveUnit.z * this.currentMoveSpeed * GameManager.getInstance().chapter.moveSpeedAddition * 0.5 * deltaTime);
            }

            if (!this.monsterModelScript.isRunning && this.movePattern !== MonsterMovePatternEnum.NO_MOVE && this.action !== MonsterActionEnum.STOP_MOVE) {
                this.monsterModelScript.playAni(MonsterAnimationType.RUN, true);
            }
        } else {
            if (!this.isDie && !this.monsterModelScript.isIdle && !this.monsterModelScript.isAttacking && !this.monsterModelScript.isHitting) {
                this.monsterModelScript.playAni(MonsterAnimationType.IDLE, true);
                this.characterRigidScript.stopMove();
            }
        }

        //冰冻持续降低攻击力和伤害
        if (this.iceDamageCountDown > 0) {
            this.iceDamageCountDown -= deltaTime;
            this.currentAttackSpeed = Number(this.baseInfo.attackSpeed) * (1 - 0.1);
            this.currentMoveSpeed = Number(this.baseInfo.moveSpeed) * (1 - 0.5);

            if (this.iceDamageCountDown <= 0) {
                this.currentAttackSpeed = Number(this.baseInfo.attackSpeed);
                this.currentMoveSpeed = Number(this.baseInfo.moveSpeed);
            }
        }

        //灼烧持续扣血
        if (this.fireDamageCountDown > 0) {
            this.fireDamageCountDown -= deltaTime;

            let countDown = Number((this.fireDamageCountDown).toFixed(2))
            countDown = countDown * 100 % 50;
            if (countDown === 0) {
                let bloodNum = Number(this.baseInfo.hp) * 0.05;
                this.refreshBlood(-bloodNum, FightTipEnum.REDUCE_BLOOD);
            }
        }

        //检查当前是否碰到障碍或者其他物体导致无法达到目标位置
        if (this.movePattern !== MonsterMovePatternEnum.NO_MOVE && !this.isArrived) {
            this.checkMoveInterval += deltaTime;
            if (this.checkMoveInterval >= 0.2) {
                this.checkMoveInterval = 0;

                let length = Utils.getTwoPositionXZLength(this.prevMoveWorldPosition.x, this.prevMoveWorldPosition.z, this.node.worldPosition.x, this.node.worldPosition.z);
                if (this.monsterModelScript.isRunning && length <= 0.01) {
                    this.stayRotateAttack();
                    // console.log("###碰到障碍, 停止移动");
                } else {
                    this.prevMoveWorldPosition.set(this.node.worldPosition);
                }
            }
        }
    }

    /**
     * 获取当前移动速度
     */
    public getCurrentMoveSpeed() {
        return this.currentMoveSpeed;
    }

    /**
     * 设置当前移动速度
     *
     * @param speed 移动速度
     */
    public setCurrentMoveSpeed(speed: number) {
        this.currentMoveSpeed = speed;
        this.characterRigidScript.initSpeed(speed, GameManager.getInstance().chapter.moveSpeedAddition);
    }

    /**
     * 是否死亡
     */
    public getIsDie() {
        return this.isDie;
    }

    /**
     * 设置死亡
     *
     * @param died 是否死亡
     */
    public setIsDie(died: boolean) {
        this.isDie = died;

        if (this.isDie) {
            this.showDie();
        }
    }

    /**
     * 初始化
     *
     * @param baseInfo base.csv
     * @param stage layer.csv
     */
    public init(baseInfo: BaseInfo, stage: Stage) {
        this.baseInfo = baseInfo;
        this.stage = stage;
        this.isDie = false;

        this.recycleWarning();
        this.monsterSMR.setMaterial(this.normalMaterial, 0);

        this.bodyNode = this.node.getChildByName("body");
        this.monsterModelScript = this.bodyNode.getComponent(MonsterModelController);
        this.monsterModelScript.playAni(MonsterAnimationType.IDLE, true);

        this.characterRigidScript = this.node.getComponent(CharacterRigidController);
        this.characterRigidScript.stopMove();

        this.currentAttackInterval = 0;
        this.isHitByPlayer = false;
        this.isInitBloodBar = false;
        this.isAllowToAttack = false;
        this.isArrived = false;
        this.checkMoveInterval = 0;
        this.iceDamageCountDown = 0;
        this.fireDamageCountDown = 0;
        this.monsterSkillNode = null;
        this.skillIndex = 0;
        this.moveUnit.set(0, 0, 0);
        this.movePattern = stage.movePattern ? stage.movePattern : this.baseInfo.movePattern;
        this.dissolveData.uEdge = 1;

        this.bloodBarScript = null!;

        this.refreshSkill();

        this.monsterModelScript.scriptMonster = this;

        this.currentAttackSpeed = Number(this.baseInfo.attackSpeed);
        this.currentMoveSpeed = Number(this.baseInfo.moveSpeed);

        this.getMinLength();
    }

    /**
     * 获取怪物和玩家之间的最小距离
     */
    protected getMinLength() {
        switch (this.node.name) {
            case "aula":
                this.minLength = 2;
                this.dissolveData.time = 3.33;
                break;
            case "boomDragon":
                this.minLength = 2;
                this.dissolveData.time = 0.87;
                break;
            case "hellFire":
                this.minLength = 2.5;
                this.dissolveData.time = 1.06;
                break;
            case "magician":
                this.minLength = 2.5;
                this.dissolveData.time = 0.87;
                break;
            case "dragon":
                this.minLength = 5;
                this.dissolveData.time = 2;
                break;
        }
    }

    /**
     * 刷新当前使用技能
     */
    protected refreshSkill() {
        this.allSkillInfo = this.stage.skill === "" ? [] : this.stage.skill.split("#");
        if (this.allSkillInfo.length) {
            this.skillIndex = this.skillIndex >= this.allSkillInfo.length ? 0 : this.skillIndex;
            let skillID = this.allSkillInfo[this.skillIndex];
            let row = CSVManager.getInstance().getRowDatas("monsterSkill", "ID", skillID);
            this.skill = SkillConverter.convertFromRow(row);
            this.skillIndex += 1;
        }
    }

    /**
     * 怪物阵亡
     *
     * @memberof Monster
     */
    public showDie() {
        this.characterRigidScript.stopMove();

        this.recycleWarning();

        AudioManager.getInstance().playSound(`${this.node.name}Die`);

        EffectManager.getInstance().showRewardBounce(this.node, "gold/gold", Number(this.baseInfo.goldNum), () => {
            if (Number(this.baseInfo.heartDropRate) >= Math.random()) {
                EffectManager.getInstance().showRewardBounce(this.node, "heart/heart", 1);
            }
        });

        //检查玩家是否拥有嗜血技能：主角击杀敌人时回复自身生命上限2%的生命值。
        if (GameManager.getInstance().gamePlayerProxy.getPlayerController().isBloodthirsty) {
            let bloodNum = GameManager.getInstance().gamePlayerProxy.getPlayerController().curHpLimit * 0.02;
            GameManager.getInstance().gamePlayerProxy.getPlayerController().addBlood(bloodNum);
        }

        // 溶解效果
        this.monsterSMR.setMaterial(this.dissolveMaterial, 0);
        tween(this.dissolveData)
            .to(this.dissolveData.time, {uEdge: 0.1})
            .start();

        this.monsterModelScript.playAni(MonsterAnimationType.DIE, false, () => {
            if (this.isDie) {
                if (GameManager.getInstance().gameBossProxy.getBossNode()) {
                    GameManager.getInstance().gameBossProxy.setBossNode(null);
                }

                if (this.bloodBarScript) {
                    this.bloodBarScript = null;
                }

                PoolManager.getInstance().putNode(this.node);
            }
        });
    }

    /**
     * 回收预警节点
     */
    public recycleWarning() {
        // 回收预警节点
        if (this.warningScript) {
            if (this.warningScript.node.parent) {
                PoolManager.getInstance().putNode(this.warningScript.node);
            }
            this.warningScript = null;
        }
    }

    /**
     * 怪物播放受击效果
     *
     * @param isArrowLaunch 是否被弹射的弓箭射中，如果是则造成普通伤害
     * @param isPassiveLightning 是否被动受到电击
     */
    public playHit(isArrowLaunch: boolean = false, isPassiveLightning: boolean = false) {
        if (this.isDie) {
            return;
        }

        AudioManager.getInstance().playSound(AudioPaths.hitMonsterSound);

        //播放受击特效
        let effectPath = "hit/hit";
        let arrEffectPath: any = [];
        let recycleTime = 1.2;

        let isHasIce = GameManager.getInstance().gamePlayerProxy.getPlayerController().isArrowIce;
        let isHasFire = GameManager.getInstance().gamePlayerProxy.getPlayerController().isArrowFire;
        let isHasLightning = GameManager.getInstance().gamePlayerProxy.getPlayerController().isArrowLightning;

        if (isHasFire || isHasIce || isHasLightning) {
            if (isHasFire && isHasIce && isHasLightning) {
                arrEffectPath = ["hit/hitFire", "hit/hitIce", "hit/hitLightning"];
            } else {
                if (isHasFire && isHasIce || isHasFire && isHasLightning || isHasIce && isHasLightning) {
                    if (isHasFire && isHasIce) {
                        arrEffectPath = ["hit/hitFire", "hit/hitIce"];
                    } else if (isHasLightning && isHasFire) {
                        arrEffectPath = ["hit/hitFire", "hit/hitLightning"];
                    } else if (isHasLightning && isHasIce) {
                        arrEffectPath = ["hit/hitIce", "hit/hitLightning"];
                    }
                } else {
                    if (isHasFire) {
                        arrEffectPath = ["hit/hitFire"];
                    } else if (isHasIce) {
                        arrEffectPath = ["hit/hitIce"];
                    } else if (isHasLightning) {
                        arrEffectPath = ["hit/hitLightning"];
                    }
                }
            }

            effectPath = arrEffectPath[Math.floor(Math.random() * arrEffectPath.length)];

            if (effectPath === "hit/hitFire") {
                //灼烧技能持续2秒
                recycleTime = 2;
            } else if (effectPath === "hit/hitIce") {
                recycleTime = 1;
            }

            //被冰冻技能击中
            if (isHasIce && this.iceDamageCountDown <= 0) {
                this.iceDamageCountDown = 1;
            }

            //被灼烧技能击中
            if (isHasFire && this.fireDamageCountDown <= 0) {
                this.fireDamageCountDown = 2;
            }
        }

        EffectManager.getInstance().loadAndPlayEffect(true, this.node, effectPath, 1, this.hitEffectPosition, null, false, true, GameManager.getInstance().gameSpeedProxy.getGameSpeed(), true, recycleTime);


        //攻击的时候霸体状态
        if (!this.monsterModelScript.isAttacking) {
            this.monsterModelScript.playAni(MonsterAnimationType.HIT);
        }

        //受到攻击的敌人会向身旁一定范围内的所有敌人发射闪电，减少生命上限5%的生命值
        if (GameManager.getInstance().gamePlayerProxy.getPlayerController().isArrowLightning && !isPassiveLightning) {
            let arrTargets = GameManager.getInstance().gameGetMonsterProxy.getNearbyMonster(this.node, true);

            if (arrTargets) {
                arrTargets.forEach((ndChild: Node) => {
                    EffectManager.getInstance().showLightningChain(this.node, ndChild);
                    let script = ndChild.getComponent(MonsterController);
                    script.playHit(false, true);
                })
            }
        }

        //怪物扣血
        if (Math.random() > Number(this.baseInfo.dodgeRate)) {
            //闪避失败
            let tipType = FightTipEnum.REDUCE_BLOOD;
            let damage = GameManager.getInstance().gamePlayerProxy.getPlayerController().curAttackPower * (1 - this.baseInfo.defensePower * GameManager.getInstance().chapter.defenseAddition / (this.baseInfo.defensePower + 400));
            let isCriticalHit = Math.random() <= GameManager.getInstance().gamePlayerProxy.getPlayerController().curCriticalHitRate;//是否暴击
            //是否暴击
            if (isCriticalHit) {
                //不是被弹射的箭击中，且不是被动受到电击
                if (!isArrowLaunch && !isPassiveLightning) {
                    damage = damage * GameManager.getInstance().gamePlayerProxy.getPlayerController().curCriticalHitDamage;
                    tipType = FightTipEnum.CRITICAL_HIT;
                }
            }

            if (isPassiveLightning) {
                damage = this.baseInfo.hp * 0.05 * (1 - Number(this.baseInfo.defensePower) / (Number(this.baseInfo.defensePower) + 400));
            }

            this.refreshBlood(-damage, tipType);
        }
    }

    /**
     * 刷新血量
     *
     * @param blood 血量
     * @param tipType 战斗提示类型
     */
    public refreshBlood(blood: number, tipType: FightTipEnum) {
        let callback = () => {
            this.bloodBarScript.refreshBlood(blood);
            UIManager.getInstance().showBloodTip(this, tipType, blood, this.bloodTipOffsetPosition);
        }

        this.currentAttackInterval = 0;

        if (!this.isInitBloodBar) {
            this.isInitBloodBar = true;
            console.log("###小怪生成新的血条", this.node.name);
            UIManager.getInstance().showMonsterBloodBar(this, Number(this.baseInfo.hp), new Vec3(), new Vec3(), () => {
                callback();
            });
        } else {
            if (this.bloodBarScript) {
                this.bloodBarScript.node.active = true;
                callback();
            }
        }
    }

    /**
     * 怪物行为
     */
    public playAction(obj: any) {
        this.action = obj.action;

        switch (obj.action) {
            // 向目标位置移动
            case MonsterActionEnum.MOVE:
                let angle = obj.value + 135;
                let radian = angle * macro.RAD;
                this.horizontal = Math.round(Math.cos(radian) * 1);
                this.vertical = Math.round(Math.sin(radian) * 1);
                this.currentAngleY = obj.value;
                this.currentAngleY = this.currentAngleY < 0 ? this.currentAngleY + 360 : this.currentAngleY > 360 ? this.currentAngleY - 360 : this.currentAngleY;
                this.moving = true;
                break;
            // 停止移动，原地转向玩家，攻击玩家
            case MonsterActionEnum.STOP_MOVE:
                let angle_1 = obj.value + 135;
                let radian_1 = angle_1 * macro.RAD;
                this.horizontal = Math.round(Math.cos(radian_1));
                this.vertical = Math.round(Math.sin(radian_1));
                this.currentAngleY = obj.value;
                this.currentAngleY = this.currentAngleY < 0 ? this.currentAngleY + 360 : this.currentAngleY > 360 ? this.currentAngleY - 360 : this.currentAngleY;
                this.moving = false;
                this.characterRigidScript.stopMove();
                // console.log("GameManager>>",GameManager.ndPlayer);
                if (GameManager.getInstance().gamePlayerProxy.getPlayerNode()) {
                    this.attackPlayer();
                } else {
                    this.monsterModelScript.playAni(MonsterAnimationType.IDLE, true);
                }
                break;
        }
    }

    /**
     * 攻击玩家
     */
    protected attackPlayer() {
        if (GameManager.getInstance().gamePlayerProxy.getPlayerController().getIsDie() || this.monsterModelScript.isAttacking) {
            return;
        }

        Vec3.subtract(this.offsetPosition_2, GameManager.getInstance().gamePlayerProxy.getPlayerNode().worldPosition, this.node.worldPosition);
        let length = this.offsetPosition_2.length();
        this.attackForward = this.offsetPosition_2.normalize().negative();
        this.attackForward.y = 0;
        this.attackPosition.set(GameManager.getInstance().gamePlayerProxy.getPlayerNode().worldPosition);

        //预警
        if (this.allSkillInfo.length && this.skill && this.skill.warning) {
            let scale = 1;
            if (this.skill.id === MonsterSkillEnum.FIRE_BALL) {
                scale = 0.1;
            } else if (this.skill.id === MonsterSkillEnum.FIRE_BALL_BIG) {
                scale = 0.4;
            } else if (this.skill.id === MonsterSkillEnum.LASER) {
                scale = 3;
            } else if (this.skill.id === MonsterSkillEnum.ENERGY_BALL) {
                scale = length;
            }

            //回收预警节点
            this.recycleWarning();

            EffectManager.getInstance().showWarning(this.skill.warning, scale, this, () => {
                this.playAttackAnimation();
            });
        } else {
            this.playAttackAnimation();
        }
    }

    /**
     * 播放攻击动画
     */
    public playAttackAnimation() {
        let attackAniName = MonsterAnimationType.ATTACK;
        if (this.baseInfo.resName === "hellFire") {
            //hellFire的攻击动画有两个，其他小怪动画只有一个
            if (!this.allSkillInfo.length) {
                //近战
                attackAniName = MonsterAnimationType.ATTACK_1;
            } else {
                //远程
                attackAniName = MonsterAnimationType.ATTACK_2;
            }
        }

        //远程
        if (this.allSkillInfo.length) {
            this.monsterModelScript.playAni(attackAniName, false, () => {
                if (!this.isDie && !this.monsterModelScript.isHitting) {
                    this.scheduleOnce(() => {
                        this.monsterMove();
                    }, Number(this.baseInfo.moveFrequency));
                }
            });
        } else {
            //近战
            let offsetLength = Utils.getTwoNodeXZLength(this.node, GameManager.getInstance().gamePlayerProxy.getPlayerNode());
            if (offsetLength <= this.minLength * this.minLengthRatio) {
                this.monsterModelScript.playAni(attackAniName, false, () => {
                    if (!this.isDie && !this.monsterModelScript.isHitting) {
                        this.scheduleOnce(() => {
                            this.monsterMove();
                        }, Number(this.baseInfo.moveFrequency));
                    }
                });
            } else {
                if (!this.isDie && !this.monsterModelScript.isHitting) {
                    this.scheduleOnce(() => {
                        this.monsterMove();
                    }, Number(this.baseInfo.moveFrequency));
                }
            }
        }
    }

    /**
     * 移动到随机位置
     */
    private moveToRandomPos() {
        this.randomMoveTryTimes -= 1;
        //随机移动：先以怪物圆环区间(1, minLength)随机移动,再朝向玩家,然后攻击
        let x = randomRange(1, 3) * Utils.getRandomDirector();
        let z = randomRange(1, 3) * Utils.getRandomDirector();
        this.targetWorldPosition.set(Utils.toFixed(this.node.worldPosition.x + x), Utils.toFixed(this.node.worldPosition.y), Utils.toFixed(this.node.worldPosition.z + z));

        let offsetLength = Utils.getTwoPositionXZLength(this.targetWorldPosition.x, this.targetWorldPosition.z, GameManager.getInstance().gamePlayerProxy.getPlayerNode().worldPosition.x, GameManager.getInstance().gamePlayerProxy.getPlayerNode().worldPosition.z);
        //当目标位置和玩家大于最小距离，进行移动
        if (offsetLength > this.minLength) {
            Vec3.subtract(this.offsetPosition, this.targetWorldPosition, this.node.worldPosition);
            this.offsetPosition.y = 0;
            Vec3.normalize(this.moveUnit, this.offsetPosition);

            this.moveToTargetWorPos(this.targetWorldPosition);
            this.moving = true;
            this.isArrived = false;
        } else {
            //否则尝试5次随机移动，都没合适的位置则进行进攻
            if (this.randomMoveTryTimes <= 0) {
                this.stayRotateAttack();
            } else {
                this.moveToRandomPos();
            }
        }
    }

    /**
     * 先移动
     */
    protected monsterMove() {
        console.log("monsterMove>>>>");
        if (this.isDie) {
            return;
        }

        if (!this.isAllowToAttack) {
            this.isAllowToAttack = true;
        }

        if (this.movePattern === MonsterMovePatternEnum.NO_MOVE) {
            //不移动，原地攻击玩家
            this.stayRotateAttack();
        } else if (this.movePattern === MonsterMovePatternEnum.RANDOM) {
            this.randomMoveTryTimes = 5;
            this.moveToRandomPos();
        } else if (this.movePattern === MonsterMovePatternEnum.FORWARD_PLAYER) {
            //面向玩家移动：先面向玩家，再移动，然后攻击
            this.moveToTargetWorPos(GameManager.getInstance().gamePlayerProxy.getPlayerNode().worldPosition);
            Vec3.subtract(this.offsetPosition, GameManager.getInstance().gamePlayerProxy.getPlayerNode().worldPosition, this.node.worldPosition);
            this.offsetPosition.y = 0;

            let offsetLength = Utils.getTwoNodeXZLength(this.node, GameManager.getInstance().gamePlayerProxy.getPlayerNode());
            //当怪物和玩家小于2个最小距离之和或者大于一个最小距离且小于两个最小距离，进行移动
            if (offsetLength > this.minLength * 2 || (offsetLength > this.minLength && offsetLength < this.minLength * 2)) {
                //单位向量
                Vec3.normalize(this.moveUnit, this.offsetPosition);
                Vec3.multiplyScalar(this.offsetPosition, this.moveUnit, this.minLength);

                if (offsetLength > this.minLength * 2) {
                    //向玩家移动2个单位向量
                    Vec3.add(this.targetWorldPosition, this.node.worldPosition, this.offsetPosition);
                } else {
                    Vec3.subtract(this.targetWorldPosition, GameManager.getInstance().gamePlayerProxy.getPlayerNode().worldPosition, this.offsetPosition);
                }

                this.targetWorldPosition.set(Utils.toFixed(this.targetWorldPosition.x), Utils.toFixed(this.node.worldPosition.y), Utils.toFixed(this.targetWorldPosition.z));
                this.isArrived = false;
                this.moving = true;
            } else {
                // 与玩家相距小于等于最小距离，怪物原地进行攻击
                this.stayRotateAttack();
            }
        }
    }

    /**
     * 怪物向目标位置移动
     */
    protected moveToTargetWorPos(targetWorPos: Vec3) {
        let angleY = this.getTwoPosAngleY(this.node.worldPosition, targetWorPos);
        this.playAction({action: MonsterActionEnum.MOVE, value: angleY});
    }

    /**
     * 移动
     *
     * @param selfWorPos 自己的位置
     * @param targetWorPos 目标的位置
     */
    protected getTwoPosAngleY(selfWorPos: Vec3, targetWorPos: Vec3) {
        let targetScreenPos = GameManager.getInstance().mainCamera.worldToScreen(targetWorPos) as Vec3;
        let selfScreenPos = GameManager.getInstance().mainCamera.worldToScreen(selfWorPos) as Vec3;
        Vec3.subtract(this.playerMonsterOffset, targetScreenPos, selfScreenPos);
        return Math.round(Math.atan2(this.playerMonsterOffset.y, this.playerMonsterOffset.x) * 180 / Math.PI);
    }

    /**
     * 怪物原地不动-旋转角度朝向玩家-攻击玩家
     *
     * @protected
     * @memberof Monster
     */
    protected stayRotateAttack() {
        let angleY = this.getTwoPosAngleY(this.node.worldPosition, GameManager.getInstance().gamePlayerProxy.getPlayerNode().worldPosition);
        this.playAction({action: MonsterActionEnum.STOP_MOVE, value: angleY});
    }

    /**
     * 向玩家释放技能
     */
    public releaseSkillToPlayer(isNormalAttack?: boolean) {
        //没有技能则使用近战
        if (!this.allSkillInfo.length) {
            let offsetLength = Utils.getTwoNodeXZLength(this.node, GameManager.getInstance().gamePlayerProxy.getPlayerNode());
            if (offsetLength <= this.minLength * this.minLengthRatio) {
                GameManager.getInstance().gamePlayerProxy.getPlayerController().reduceBlood(this.baseInfo);
            }
            return;
        }

        //加载对应技能
        ResourceUtils.loadEffect(`${this.skill.resourceName}/${this.skill.resourceName}`).then((prefab: any) => {
            if (this.moving) {
                return;
            }
            this.monsterSkillNode = PoolManager.getInstance().getNode(prefab, GameManager.getInstance().node);
            this.monsterSkillNode.setWorldPosition(this.node.worldPosition.x, 2.5, this.node.worldPosition.z);
            this.monsterSkillNode.forward = this.attackForward.negative();

            let scriptSkillCollider: any = null!;

            //怪物技能初始化
            switch (this.skill.id) {
                case MonsterSkillEnum.ENERGY_BALL:
                    scriptSkillCollider = this.monsterSkillNode.getComponent(EnergyBallEffect);
                    scriptSkillCollider.init(this.skill, this.baseInfo, this);
                    break;
                case MonsterSkillEnum.FIRE_BALL:
                    scriptSkillCollider = this.monsterSkillNode.getComponent(FireBallEffect);
                    scriptSkillCollider.init(this.skill, this.baseInfo, this);
                    break;
                case MonsterSkillEnum.DISPERSION:
                    this.monsterSkillNode.children.forEach((ndChild: Node, idx: number) => {
                        let scriptSkillCollider = ndChild.getComponent(DispersionEffect);
                        scriptSkillCollider.init(this.skill, this.baseInfo);
                    })
                    break;
                case MonsterSkillEnum.TORNADO:
                    scriptSkillCollider = this.monsterSkillNode.getComponent(TornadoEffect);
                    scriptSkillCollider.init(this.skill, this.baseInfo, this);
                    break;
                case MonsterSkillEnum.FIRE_BALL_BIG:
                    scriptSkillCollider = this.monsterSkillNode.getComponent(FireBallBigEffect);
                    scriptSkillCollider.init(this.skill, this.baseInfo, this);
                    break;
                case MonsterSkillEnum.DISPERSION_SURROUND:
                    this.monsterSkillNode.children.forEach((ndChild: Node) => {
                        let scriptSkillCollider = ndChild.getComponent(DispersionSurroundEffect);
                        scriptSkillCollider.init(this.skill, this.baseInfo);
                    })
                    break;
                case MonsterSkillEnum.LASER:
                    scriptSkillCollider = this.monsterSkillNode.getComponent(LaserEffect);
                    scriptSkillCollider.init(this.skill, this.baseInfo, this);
                    break;
            }

            this.refreshSkill();
        })
    }
}

